<script setup lang="ts">
import { cloneDeep } from "lodash";
import {
  ReloadOutlined,
  ColumnHeightOutlined,
  ColumnWidthOutlined,
  PlusOutlined
} from "@ant-design/icons-vue";
import { computed, watch, reactive } from "vue";
import type { PropType } from "vue";
import type { TableColumnProps } from "ant-design-vue";

defineOptions({ name: "WebxTable" });
const emits = defineEmits(["refresh", "create"]);
const props = defineProps({
  // 表格列
  columns: { type: Array as PropType<Column[]>, default: () => [] },
  // 表格紧凑度
  size: { type: String, default: "small" },
  // 渲染新增按钮
  showCreate: { type: Boolean, default: true }
});

const webxTable = reactive({
  // 当前紧凑度
  size: props.size,
  // 当前显示的列
  columnsWithVisible: [] as Column[],
  // 刷新
  onRefresh() {
    emits("refresh");
  },
  // 紧凑度调整
  onSizeChange({ key }: any) {
    webxTable.size = key;
  },
  // 新增
  onCreate() {
    emits("create");
  }
});
// 计算属性
// 为了避免类型实例化过深的问题，明确指定返回类型
const visibleColumns = computed<Column[]>(() =>
  webxTable.columnsWithVisible.filter((col: Column) => col.visible).map(col => ({
    ...col,
    customRender: col.customRender ? col.customRender : ({ text, record }) => {
      // 新增路径解析逻辑
      const splitPath = (path: string) => path.split('.').filter(Boolean)
      const getNestedValue = (obj: any, pathArray: string[]) => 
        pathArray.reduce((acc, cur) => acc?.[cur], obj)
        
      return col.dataIndex ? 
        getNestedValue(record, splitPath(col.dataIndex as string)) : 
        text
    }
  }))
);
// 勾选的表格列
const selectedColumns = computed<string[]>({
  get() {
    return webxTable.columnsWithVisible
      .filter((col: any) => col.visible)
      .map((col: any) => col.dataIndex);
  },
  set(values: string[]) {
    webxTable.columnsWithVisible = webxTable.columnsWithVisible.map((col: any) => ({
      ...col,
      visible: values.includes(col.dataIndex)
    }));
  }
});

// 监听器
watch(
  () => props.columns,
  newVal => {
    webxTable.columnsWithVisible = cloneDeep(newVal).map(col => ({
      ...col,
      visible: col.visible ?? true
    }));
  },
  { immediate: true, deep: true }
);

type Column = {
  visible?: boolean;
} & TableColumnProps;
</script>

<template>
  <div class="webx-table bg-white p-4 rounded">
    <div class="flex justify-between items-center mb-4">
      <div>
        <slot name="headLeft" />
      </div>
      <div class="flex gap-2">
        <slot name="headRight" />
        <AButton type="primary" @click="webxTable.onCreate" v-if="showCreate">
          <PlusOutlined />
          新增
        </AButton>
        <ATooltip title="刷新">
          <ReloadOutlined @click="webxTable.onRefresh" />
        </ATooltip>

        <ATooltip title="密度">
          <ADropdown :trigger="['click']">
            <ColumnHeightOutlined />
            <template #overlay>
              <AMenu :selectedKeys="[webxTable.size]" @click="webxTable.onSizeChange">
                <AMenuItem key="default">默认</AMenuItem>
                <AMenuItem key="middle">中等</AMenuItem>
                <AMenuItem key="small">紧凑</AMenuItem>
              </AMenu>
            </template>
          </ADropdown>
        </ATooltip>

        <ATooltip title="列设置">
          <APopover placement="bottomRight" trigger="click">
            <ColumnWidthOutlined />
            <template #content>
              <ACheckboxGroup v-model:value="selectedColumns">
                <ASpace direction="vertical">
                  <ACheckbox
                    v-for="column in webxTable.columnsWithVisible"
                    :key="column.dataIndex"
                    :value="column.dataIndex"
                  >
                    {{ column.title }}
                  </ACheckbox>
                </ASpace>
              </ACheckboxGroup>
            </template>
          </APopover>
        </ATooltip>
      </div>
    </div>

    <ATable bordered v-bind="$attrs" :size="webxTable.size" :columns="visibleColumns">
      <!-- 透传所有插槽 -->
      <template v-for="(_, slotName) in $slots" #[slotName]="slotData">
        <slot :name="slotName" v-bind="slotData" />
      </template>
    </ATable>
  </div>
</template>

<style lang="less" scoped></style>
